SPORE.$Import('core.core');

/*
---

name: Array

description: Contains Array Prototypes like each, contains, and erase.

license: MIT-style license.

requires: Type

provides: Array

...
*/

SPORE.register('core.array',function($ns){

	Array.implement({
	
		/*<!ES5>*/
		every: function(fn, bind){
			for (var i = 0, l = this.length; i < l; i++){
				if ((i in this) && !fn.call(bind, this[i], i, this)) return false;
			}
			return true;
		},
	
		filter: function(fn, bind){
			var results = [];
			for (var i = 0, l = this.length; i < l; i++){
				if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]);
			}
			return results;
		},
	
		indexOf: function(item, from){
			var len = this.length;
			for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
				if (this[i] === item) return i;
			}
			return -1;
		},
	
		map: function(fn, bind){
			var results = [];
			for (var i = 0, l = this.length; i < l; i++){
				if (i in this) results[i] = fn.call(bind, this[i], i, this);
			}
			return results;
		},
	
		some: function(fn, bind){
			for (var i = 0, l = this.length; i < l; i++){
				if ((i in this) && fn.call(bind, this[i], i, this)) return true;
			}
			return false;
		},
		/*</!ES5>*/
	
		clean: function(){
			return this.filter(function(item){
				return item != null;
			});
		},
	
		invoke: function(methodName){
			var args = Array.slice(arguments, 1);
			return this.map(function(item){
				return item[methodName].apply(item, args);
			});
		},
	
		associate: function(keys){
			var obj = {}, length = Math.min(this.length, keys.length);
			for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
			return obj;
		},
	
		link: function(object){
			var result = {};
			for (var i = 0, l = this.length; i < l; i++){
				for (var key in object){
					if (object[key](this[i])){
						result[key] = this[i];
						delete object[key];
						break;
					}
				}
			}
			return result;
		},
	
		contains: function(item, from){
			return this.indexOf(item, from) != -1;
		},
	
		append: function(array){
			this.push.apply(this, array);
			return this;
		},
	
		getLast: function(){
			return (this.length) ? this[this.length - 1] : null;
		},
	
		getRandom: function(){
			return (this.length) ? this[Number.random(0, this.length - 1)] : null;
		},
	
		include: function(item){
			if (!this.contains(item)) this.push(item);
			return this;
		},
	
		combine: function(array){
			for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
			return this;
		},
	
		erase: function(item){
			for (var i = this.length; i--;){
				if (this[i] === item) this.splice(i, 1);
			}
			return this;
		},
	
		empty: function(){
			this.length = 0;
			return this;
		},
	
		flatten: function(){
			var array = [];
			for (var i = 0, l = this.length; i < l; i++){
				var type = typeOf(this[i]);
				if (type == 'null') continue;
				array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]);
			}
			return array;
		},
	
		pick: function(){
			for (var i = 0, l = this.length; i < l; i++){
				if (this[i] != null) return this[i];
			}
			return null;
		},
	
		hexToRgb: function(array){
			if (this.length != 3) return null;
			var rgb = this.map(function(value){
				if (value.length == 1) value += value;
				return value.toInt(16);
			});
			return (array) ? rgb : 'rgb(' + rgb + ')';
		},
	
		rgbToHex: function(array){
			if (this.length < 3) return null;
			if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
			var hex = [];
			for (var i = 0; i < 3; i++){
				var bit = (this[i] - 0).toString(16);
				hex.push((bit.length == 1) ? '0' + bit : bit);
			}
			return (array) ? hex : '#' + hex.join('');
		}
	
	});

});